package com.lzyyj.gmis.base.webui.action;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.json.annotations.JSON;

import com.lzyyj.common.BeanUtilsExt;
import com.lzyyj.common.BeanWrapper;
import com.lzyyj.common.CglibWrapper;
import com.lzyyj.common.GenericsUtils;
import com.lzyyj.common.Page;
import com.lzyyj.gmis.base.dao.IBaseDao;
import com.lzyyj.gmis.base.service.BaseService;
import com.lzyyj.gmis.base.service.IBaseService;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;

@SuppressWarnings("serial")
public class BaseAction<T, PK extends Serializable> extends ActionSupport {

	protected static Logger LOG = LoggerFactory.getLogger(BaseAction.class);

	protected Class<T> itemClass; // DAO所管理的Entity类型.

	public static final String MANAGE = "manage";
	public static final String LIST = "list";
	public static final String VIEW = "view";
	public static final String ADD = "add";
	public static final String EDIT = "edit";
	public static final String SAVE = "save";
	public static final String DELETE = "del";
	public static final String JSON = "json";
	public static final String ARRAY_JSON = "arrayJson";
	
	private Boolean ajax;

	public boolean isAjax() {
		if (ajax==null){
			HttpServletRequest request= (HttpServletRequest)ServletActionContext.getRequest();;   
			ajax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
			
		}
		return ajax;
	}

	public void setAjax(boolean ajax) {
		this.ajax = ajax;
	}

	protected IBaseService<T, PK> baseService;

	protected T item;

	public String getExampleProperties() {
		return (String) page.getCondition().get(IBaseDao.EXAMPLE_PROPERTIES);
	}

	public void setExampleProperties(String exampleProperties) {
		page.getCondition().put(IBaseDao.EXAMPLE_PROPERTIES, exampleProperties);
	}

	protected Page<T> page = new Page<T>();
	
	private String itemPropertyList;

	public String getItemPropertyList() {
		return itemPropertyList;
	}

	public void setItemPropertyList(String itemPropertyList) {
		this.itemPropertyList = itemPropertyList;
	}

	protected Map<String, Object> mapResult = new HashMap<String, Object>();
	
	protected List<Object> listResult = new ArrayList<Object>();

	public List<Object> getListResult() {
		return listResult;
	}

	public void setListResult(List<Object> listResult) {
		this.listResult = listResult;
	}

	public String getEntityClass() {
		return itemClass.getName();
	}

	public void setEntityClass(String className) {
		try {
			itemClass = (Class<T>) Class.forName(className);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected String idName;

	public String getIdName() {
		return idName;
	}

	public void setIdName(String idName) {
		this.idName = idName;
	}

	/**
	 * 改变顺序时的移动偏移量
	 */
	private int offset = 0;

	/**
	 * 操作类型，默认为列表管理
	 */
	private String operate;

	/**
	 * 当前操作行序号, 0起序,-1为无
	 */
	private int index = -1;
	
	private String definedResult = "";

	/**
	 * 自定义返回视图
	 * @return
	 */
	public String getDefinedResult() {
		return definedResult;
	}

	public void setDefinedResult(String definedResult) {
		this.definedResult = definedResult;
	}

	public List<Map<String, Object>> getEntityNameList() {
		List<Map<String, Object>> entityNameList;

		if (baseService != null) {
			entityNameList = baseService.getEntityNameList();
		} else {
			entityNameList = new ArrayList<Map<String, Object>>();
		}

		return entityNameList;
	}

	/**
	 * 改变顺序时的移动偏移量
	 */
	public int getOffset() {
		return offset;
	}

	public Map<String, Object> getSession() {
		return ActionContext.getContext().getSession();
	}

	public IBaseService<T, PK> getBaseService() {
		if (baseService == null) {
			return baseService;
		} else {
			if (baseService.getEntityClass() != null && baseService.getEntityClass() != this.itemClass) {
				return baseService.getBaseService(itemClass);
			} else {
				return baseService;
			}
		}
	}

	public void setBaseService(IBaseService<T, PK> baseService) {
		this.baseService = baseService;
		try {
			idName = baseService.getIdName();
			if (itemClass == Object.class && baseService.getEntityClass() != Class.class) {
				if (baseService.getEntityClass()!=null){
					page.setFindByExample(baseService.getEntityClass().newInstance());
				}else{
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public T getItem() {
		return item;
	}

	public void setItem(T item) {
		this.item = item;
	}

	public String getPropertyList() {
		String propertyList = (String) page.getCondition().get(IBaseDao.PROPERTY_LIST);
		if (propertyList == null || propertyList.length() == 0) {
			try {
				propertyList = baseService.getPropertyList();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			setPropertyList(propertyList);
		}
		return propertyList;
	}

	public void setPropertyList(String propertyList) {
		page.getCondition().put(IBaseDao.PROPERTY_LIST, propertyList);
	}

	public List<String> getProperty() {
		List<String> properties = new ArrayList<String>();

		String propertieString = (String) page.getCondition().get("propertyList");
		if (propertieString != null) {
			for (String property : propertieString.split(",")) {
				properties.add(property);
			}
		}

		return properties;
	}

	public void setProperty(List<String> properties) {
		String propertyList = null;
		for (String property : properties) {
			if (propertyList == null || propertyList.length() == 0) {
				propertyList = property;
			} else {
				propertyList += "," + property;
			}
		}
		setPropertyList(propertyList);
	}

	public T getExample() {
		return page.getFindByExample();
	}

	public void setExample(T example) {
		page.setFindByExample(example);
	}

	public String getOperate() {
		return operate;
	}

	public void setOperate(String op) {
		this.operate = op;
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(int index) {
		this.index = index;
	}

	/**
	 * 改变顺序时的移动偏移量
	 */
	public void setOffset(int offset) {
		this.offset = offset;
	}

	public Page<T> getPage() {
		return page;
	}

	public void setPage(Page<T> page) {
		this.page = page;
	}

	public List<T> getList() {
		return page.getData();
	}

	public void setList(List<T> list) {
		this.getPage().setData(list);
	}

	@JSON
	public Map<String, Object> getMapResult() {
		return mapResult;
	}

	public void setMapResult(Map<String, Object> mapResult) {
		this.mapResult = mapResult;
	}

	@SuppressWarnings("unchecked")
	private void parseEntityClass(Class<T> entityClass) {
		String description;
		if (entityClass==null){
			this.itemClass = (Class<T>)GenericsUtils.getSuperClassGenricType(getClass(), BaseAction.class, "T");
			description = "默认构造";
		}else{
			this.itemClass = entityClass;
			description = "带参构造";
		}
		Class<PK> pkClass = (Class<PK>)GenericsUtils.getSuperClassGenricType(getClass(), BaseService.class, 1);
		LOG.debug(getClass().getSimpleName()+" "+description+"，"+" 管理实体: "+this.itemClass+" 主键："+pkClass);
	}

	@SuppressWarnings("unchecked")
	public BaseAction() {
		parseEntityClass(null);
		initItem();
	}

	public BaseAction(Class<T> clazz) {
		parseEntityClass(clazz);
		initItem();
	}

	private void initItem() {
		if (itemClass!=null){
			if (itemClass.isInterface()){
				try {
					item = BeanWrapper.wrap(itemClass, "", null);
					page.setFindByExample(BeanWrapper.wrap(itemClass, "", null));
				} catch (Exception e) {
					item = CglibWrapper.wrap(itemClass, new HashMap<String, Object>());
					page.setFindByExample(CglibWrapper.wrap(itemClass, new HashMap<String, Object>()));
					e.printStackTrace();
				}
			}else{
				try {
					item = itemClass.newInstance();
					page.setFindByExample(itemClass.newInstance());
				} catch (Exception e) {
					item = CglibWrapper.wrap(itemClass, new HashMap<String, Object>());
					page.setFindByExample(CglibWrapper.wrap(itemClass, new HashMap<String, Object>()));
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 添加项目
	 * 
	 * @return
	 */
	public String add() {
		operate = ADD;
		return manage();
	}

	public String del() {
		operate = DELETE;
		return manage();
	}

	/**
	 * 修改项目
	 * 
	 * @return
	 */
	public String edit() {
		operate = EDIT;
		return manage();
	}

	/**
	 * 保存项目权限配置
	 * 
	 * @return
	 */
	public String save() {
		String retResult;
		try {
			saveItem();
			addActionMessage("保存成功！");
			retResult = SUCCESS;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			addActionError("发生错误：" + e);
			retResult = ERROR;
		}
		retResult = checkAjax(retResult);
		return retResult;
	}

	/**
	 * 检查ajax调用，并针对ajax调用调整返回结果
	 * @param retResult
	 * @return
	 */
	public String checkAjax(String retResult) {
		if (isAjax()){
			if (hasActionErrors()){
				mapResult.put("success",false);
				mapResult.put("errorMessage", ""+this.getActionErrors());
			}else{
				mapResult.put("success",true);
				mapResult.put("message", ""+getActionMessages());
			}
			retResult = JSON;
		}
		return retResult;
	}
	
	public String list() {
		try {
			// 获取对象列表
			if (getBaseService() == null) {
				this.addActionError("系统部署错误，没有配置业务服务模块！");
				return ERROR;
			} else {
				page = getBaseService().manage(page);
			}
		} catch (Exception e) {
			this.addActionError("发生错误："+e);
			return ERROR;
		}
		return SUCCESS;
	}

	public String view() {
		String result;
		
		operate = VIEW;
		try {
			if (item == null) {
				this.addActionError("没有指定要查看的项目！");
				result = ERROR;
			} else {
				// 查看并修改
				if (getBaseService() == null) {
					this.addActionError("系统部署错误，没有配置业务服务模块！");
					result = ERROR;
				} else {
					item = getBaseService().get(item);
				}
				if (item == null) {
					addActionError("没有找到要查看的项目！");
					result = ERROR;
				}
			}
		} catch (Exception e) {
			this.addActionError(e.getMessage());
			result = ERROR;
		}
		mapResult.put("item", item);
		
		result = SUCCESS;
		
		result = checkAjax(result);

		return result;
	}

	public String manage() {
		String result;
		if (getBaseService() == null) {
			this.addActionError("系统部署错误，没有配置业务服务模块！");
			return ERROR;
		} else {
			try {
				if (operate != null && operate.length() > 1) {
					if (SAVE.equalsIgnoreCase(operate)) {

						long startIndex = getBaseService().getIndex(item, page);
						page.setStartIndex(startIndex);
						saveItem();

						operate = MANAGE;
						index = -1;
					} else if (DELETE.equalsIgnoreCase(operate)) {

						delItem();

						operate = MANAGE;
						index = -1;
					} else if (!(MANAGE.equalsIgnoreCase(operate) || ADD.equalsIgnoreCase(operate)
							|| EDIT.equalsIgnoreCase(operate) || VIEW.equalsIgnoreCase(operate))) {
						// 如果是其它未知操作
						Class<? extends IBaseService> baseServiceClass = getBaseService().getClass();
						Method method = BeanUtilsExt.getMethod(baseServiceClass, operate, item.getClass(), String.class);
						if (method != null) {
							item = (T) method.invoke(getBaseService(), new Object[] { item, getPropertyList() });
						} else {
							addActionError("未知的操作！");
						}

						operate = MANAGE;
						index = -1;
					}
				}

				page = getBaseService().manage(page);
				
				if (EDIT.equalsIgnoreCase(operate)) {
					if (index >= 0 && index < page.getData().size()) {
						item = page.getData().get(index);
					}
					getForModify();
				} else if (VIEW.equalsIgnoreCase(operate)) {
					if (index >= 0 && index < page.getData().size()) {
						item = page.getData().get(index);
					}
				} else if (ADD.equalsIgnoreCase(operate)) {
					item = getBaseService().getNew(page.getFindByExample(), getItemPropertyList());
					index = -1;
				} else {
					item = null;
				}
				itemClass = getBaseService().getEntityClass();
				result = SUCCESS;
			} catch (Exception e) {
				this.addActionError(e.toString());
				e.printStackTrace();
				result = ERROR;
			}
		}
		
		result = checkAjax(result);
		
		return result;
	}

	private void delItem() throws IllegalAccessException, InvocationTargetException, Exception {
		Class<? extends IBaseService> baseServiceClass = getBaseService().getClass();
		Method m = BeanUtilsExt.getMethod(baseServiceClass, DELETE, item.getClass());
		if (m != null) {
			m.invoke(getBaseService(), new Object[] { item });
		} else {
			getBaseService().del(item);
		}
	}

	private void saveItem() throws IllegalAccessException, InvocationTargetException, Exception {
		Class<? extends IBaseService> baseServiceClass = getBaseService().getClass();
		if (getItemPropertyList() == null || getItemPropertyList().length() == 0) {
			Method m = BeanUtilsExt.getMethod(baseServiceClass, SAVE, item.getClass());
			if (m != null) {
				item = (T) m.invoke(getBaseService(), new Object[] { item });
			} else {
				item = getBaseService().save(item);
			}
		} else {
			Method m;
			try {
				m = baseServiceClass.getMethod(SAVE, item.getClass(), String.class);
			} catch (Exception e) {
				m = null;
			}
			if (m != null) {
				item = (T) m.invoke(getBaseService(), new Object[] { item, getItemPropertyList() });
			} else {
				try {
					m = baseServiceClass.getMethod(SAVE, item.getClass());
				} catch (Exception e) {
					m = null;
				}
				if (m != null) {
					item = (T) m.invoke(getBaseService(), new Object[] { item });
				} else {
					item = getBaseService().save(item, getItemPropertyList());
				}
			}
		}
	}

	private void getForModify() throws Exception {
		item = getBaseService().getForModify(item, getItemPropertyList());
	}

	public String changeOrder() {
		try {
			if (item == null) {
				this.addActionError("没有指定要查看的项目！");
				return ERROR;
			} else {
				this.addActionError("改变序号功能还未实现！");
				return ERROR;
			}
		} catch (Exception e) {
			this.addActionError(e.getMessage());
			return ERROR;
		}
	}

}
